package remotecache

import (
	"bytes"
	"encoding/gob"
	"github.com/redis/go-redis/v9"

	"go-caipu/pkg/setting"
)

func init() {
	gob.Register(map[string]itemWithTTL{})
}

const (
	DeployStandalone = "standalone"
	DeployCluster    = "cluster"
)

type Cache struct {
	store Driver
}

func (c Cache) Set(key string, value interface{}, ttl int) error {
	return c.store.Set(key, value, ttl)
}

func (c Cache) Get(key string) (interface{}, bool) {
	return c.store.Get(key)
}

func (c Cache) Gets(keys []string, prefix string) (map[string]interface{}, []string) {
	return c.store.Gets(keys, prefix)
}

func (c Cache) Sets(values map[string]interface{}, prefix string) error {
	return c.store.Sets(values, prefix)
}

func (c Cache) Delete(keys []string, prefix string) error {
	return c.store.Delete(keys, prefix)
}

func (c Cache) Persist(path string) error {
	return c.store.Persist(path)
}

func (c Cache) Restore(path string) error {
	return c.store.Restore(path)
}

// GetSettings 根据名称批量获取设置项缓存
func (c Cache) GetSettings(keys []string, prefix string) (map[string]string, []string) {
	raw, miss := c.Gets(keys, prefix)

	res := make(map[string]string, len(raw))
	for k, v := range raw {
		res[k] = v.(string)
	}

	return res, miss
}

// SetSettings 批量设置站点设置缓存
func (c Cache) SetSettings(values map[string]string, prefix string) error {
	var toBeSet = make(map[string]interface{}, len(values))
	for key, value := range values {
		toBeSet[key] = interface{}(value)
	}
	return c.Sets(toBeSet, prefix)
}

func ProvideCache(cfg *setting.Cfg, client *redis.Client) (*Cache, error) {
	var driver Driver
	switch cfg.Application.Deploy {
	case DeployStandalone:
		driver = NewMemoStore()
	case DeployCluster:
		driver = NewRedisStore(client)
	default:
		panic(" no provider found cache driver ,please check config/default.yal ")
	}
	return &Cache{store: driver}, nil
}

type item struct {
	Value interface{}
}

func serializer(value interface{}) ([]byte, error) {
	var buffer bytes.Buffer
	enc := gob.NewEncoder(&buffer)
	storeValue := item{
		Value: value,
	}
	err := enc.Encode(storeValue)
	if err != nil {
		return nil, err
	}
	return buffer.Bytes(), nil
}
func deserializer(value []byte) (interface{}, error) {
	var res item
	buffer := bytes.NewReader(value)
	dec := gob.NewDecoder(buffer)
	err := dec.Decode(&res)
	if err != nil {
		return nil, err
	}
	return res.Value, nil
}

type Driver interface {

	//Set 设置值，ttl为过期时间，单位为秒
	Set(key string, value interface{}, ttl int) error

	//Get 取值，并返回是否成功
	Get(key string) (interface{}, bool)

	//Gets 批量取值，返回成功取值的map即不存在的值
	Gets(keys []string, prefix string) (map[string]interface{}, []string)

	//Sets 批量设置值，所有的key都会加上prefix前缀
	Sets(values map[string]interface{}, prefix string) error

	//Delete 删除值
	Delete(keys []string, prefix string) error

	//Persist Save in-memory cache to disk
	Persist(path string) error

	//Restore cache from disk
	Restore(path string) error
}
